多地组网:Tailscale Subnat 在异地办公场景下的工程实践

九个办公点,如何异地组网实现设备统一监测?设备成本仅需110元/台,跨省延迟仅 22ms !低成本组网解决方案,实现快速部署与运维提效。

1. 技术决策背景

随着我司规模逐渐扩大,我作为我司唯一的基础设施运维,要支撑维护 9 个办公点的录像设备、NAS、打印机,急需打通各个办公点的网络,将所有设施纳入统一监测和管控

作为一名业余运维,我对传统组网方案了解有限,只知道有 VPN专线SD-WANTailscaleZerotier One 几种方案,但是具体情况却不太了解。不过,经验不够 AI 来凑,Deepseek 给出了下面的介绍:

1.1 传统组网方案对比分析

方案类型 优势 劣势 适用场景
专线互联 <10ms延迟
99.99%可靠性
万元级月费
部署周期长
金融/医疗核心系统
IPsec VPN 厂商兼容性好 配置复杂
NAT穿透困难
少量固定站点互联
SD-WAN 智能选路
QoS保障
年费高昂
需要专用设备
跨国企业分支机构
Tailscale 零配置部署
按需计费
依赖公网质量 中小型多站点互联

恰好,我对 Tailscale 有着非常丰富的经验。几年前在南京的时候,我使用过 Zerotier OneTailscale 来支持影视项目的远程协作远程剪辑远程调色,对其简单的配置和极低的延迟印象深刻。

1.2 先简单介绍一下 Tailscale

Tailscale是基于WireGuard内核构建的零配置组网工具,其核心技术突破体现在三大层面:

  • 智能NAT穿透:通过STUN协议自动建立P2P直连,当直连受阻时智能启用中继节点(DERP服务器)
  • 身份联邦系统:集成 Google Workspace / Microsoft 365 等企业身份源,实现设备级RBAC控制
  • 动态路由管理:支持子网路由通告(Subnet Routing)和策略路由(Exit Node)

当然,Zerotier One 也是一个不错的选择,不过:

1.3 Zerotier One 和 Tailscale 对比

  • Zerotier One 现在仅支持 10 个免费设备了,而 Tailscale 支持免费 100 个设备
  • Tailscale 官方仍然在积极维护 QNAP 套件,不进入终端就可接入,而 Zerotier 只能用第三方套件,没有安全保障。
  • Tailscale 的部署以及 Subnet 配置更加简单,并且有极其完善的参考文档 —— 完善到我只需要复制粘贴回车,再到管理界面上去允许路由到 Subnet 即可。

综合来看,采用 Tailscale 组网,是我们现阶段成本最低、能快速上线、维护起来最简单的方案。


2. Subnet Router 部署实战

2.1 设备选型

运行 Tailscale ,只需要在每个办公点的子网中部署一台 Linux 服务器即可,如果不考虑外形,甚至还可以用树莓派。

我选用了戴尔 Wyse 3040 瘦客户机:

  • 处理器:Intel Atom x5-Z8350
  • 内存:2GB DDR3L
  • 存储:8GB eMMC
  • 网络:千兆网口
  • 价格:咸鱼二手 110 元/台

image

2.2 系统定制

戴尔 Wyse 3040 瘦客户机预装是 ThinOS 系统,我需要改为安装 Ubuntu,从 Ubuntu 官网 下载Ubuntu Server 24.04.1 LTS 的镜像,存储进 Ventoy 的 U 盘,开始安装。

选用哪个系统版本?

最好选用最新的 LTS 发行版,因为其他老旧版本,你甚至找不到可用的国内软件镜像源。

安装前,需要先解锁 BIOS :

连接好鼠标键盘,开机时按 F2 进入 BIOS,然后点击页面下方的 🔒 图标,输入密码:Fireport ,然后就可以可以切换启动项了。

还有其他设置项需要配置吗?

最好也同时设置一下上电自动开机,这样在停电后恢复电力时,无需人工干预就能自动恢复运行。

系统安装过程不再赘述。

在设置主机名时,最好设置一个清晰简明的主机名,比如我设置的是<mycom>-gateway-<location>

安装中途,如果提示无法自动卸载安装媒体,要求移出安装媒体后按回车键确认,拔掉U盘,然后回车即可。

等待系统自动重启后,会进入终端。

进入终端后,我们先登录配置一下 ssh 密钥:

echo "公钥内容" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

配置好后,测试使用 ssh 密钥可以正常登录了,就可以把密码登录禁用掉,提高安全性。

sudo nano /etc/ssh/sshd_config
# 找到 PasswordAuthentication 项目配置为 no
sudo systemctl restart sshd
# 有必要的话更新一下所有的软件包
sudo apt full-upgrade
# 还可以重启一下系统 
sudo reboot

2.3 软件安装和配置

先安装一下 ifconfig 命令:

sudo apt install -y net-tools

根据 Download | Tailscale 安装 tailscale 软件包,直接执行命令:

# 一键安装脚本
curl -fsSL https://tailscale.com/install.sh | sh

由于 Tailscale 服务器在国外,所以安装比较慢,需要等待很久。等待安装完成后,执行命令:

sudo tailscale up

终端中会输出一个网址,将此网址输入到浏览器中打开,然后用 Tailscale 账号登录验证,选择网络加入,再去控制台允许设备接入即可。

image

对于这种长期运行的设备,建议在控制台中点击 Disable key expiry 关掉密钥过期,否则设备上的 Tailscale 客户端登录态会在 180 天后过期,密钥过期后,必须在客户端上重新登录,否则不能再通过 Tailscale 的 IP 远程连接。禁用掉密钥过期后,会在设备名下方出现 Expiry disabled 标识。

需要更换自动分配的 IP 和设备名吗?
  • 我的习惯将其改为和上一台设备连续的 ip ,因为这样才能更方便的使用子网网段来配置防火墙。
  • 设备名会自动读取设备 domain ,一般不需要设置。

现在,我们可以用另一台接入了 Tailscale 的设备测试一下是否可以通过 tailscale ip 进行连接。

PS C:\Users\admin> ping 100.***.***.***

正在 Ping 100.***.***.*** 具有 32 字节的数据:
来自 100.***.***.*** 的回复: 字节=32 时间=26ms TTL=64
来自 100.***.***.*** 的回复: 字节=32 时间=6ms TTL=64
来自 100.***.***.*** 的回复: 字节=32 时间=7ms TTL=64
来自 100.***.***.*** 的回复: 字节=32 时间=7ms TTL=64

100.***.***.*** 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 6ms,最长 = 26ms,平均 = 11ms

如果一切正常,就可以给系统关机断电。

2.4 迁移设备到办公点 B

将这台戴尔 Wyse 3040 瘦客户机与电源线、网线,一起打包,寄送给办公点 B 的同事。待同事收到后,微信视频指导同事将其安装到弱电箱中,插好电源和网线。

此时,可以尝试开始测通该主机:

ping 100.***.***.*** -t
正在 Ping 100.***.***.*** 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
请求超时。
请求超时。
请求超时。
请求超时。
来自 100.***.***.*** 的回复: 字节=32 时间=6ms TTL=64
来自 100.***.***.*** 的回复: 字节=32 时间=6ms TTL=64
来自 100.***.***.*** 的回复: 字节=32 时间=7ms TTL=64

等待到该主机回复后,建立 SSH 连接:

ssh ubuntu@example-gateway-01

2.5 配置 Subnet

将 Linux 设备用作子网路由器需要 IP 转发。我们参考Subnet routers · Tailscale Docs,对于 Ubuntu 系统,可以执行 ls -la /etc/sysctl.d 来验证/etc/sysctl.d 目录是否存在:

ls -la /etc/sysctl.d

total 48
drwxr-xr-x   2 root root 4096 Jan 22 11:15 .
drwxr-xr-x 108 root root 4096 Jan 31 06:49 ..
-rw-r--r--   1 root root   77 Mar 31  2024 10-console-messages.conf
-rw-r--r--   1 root root  490 Mar 31  2024 10-ipv6-privacy.conf
-rw-r--r--   1 root root 1229 Mar 31  2024 10-kernel-hardening.conf
-rw-r--r--   1 root root 1184 Mar 31  2024 10-magic-sysrq.conf
-rw-r--r--   1 root root  164 Mar 31  2024 10-map-count.conf
-rw-r--r--   1 root root  158 Mar 31  2024 10-network-security.conf
-rw-r--r--   1 root root 1292 Mar 31  2024 10-ptrace.conf
-rw-r--r--   1 root root  506 Mar 31  2024 10-zeropage.conf
lrwxrwxrwx   1 root root   14 Aug  8 14:51 99-sysctl.conf -> ../sysctl.conf
-rw-r--r--   1 root root  798 Mar 24  2024 README.sysctl

目录存在,按照文档中,我们应该执行以下命令来启用 IP 转发:

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

然后,重新运行 tailscale up 命令,不过这次要加上 --advertise-routes 参数来公布子网路由

我们先看看这个办公点的局域网网段是什么。运行 ifconfig 查一下:

ifconfig
enp1s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.3  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 240e:****:****:****:****:****:****:****  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::****:****:****:****  prefixlen 64  scopeid 0x20<link>
        ether 54:**:**:**:**:**  txqueuelen 1000  (Ethernet)
        RX packets 9057171  bytes 2323627170 (2.3 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8582678  bytes 1708579171 (1.7 GB)
        TX errors 124  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 1010  bytes 109360 (109.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1010  bytes 109360 (109.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

查得:

  • IP: 192.168.2.3
  • 子网掩码:255.255.255.0

则办公点B的局域网网段为 192.168.2.0/24 ,那么我们就可以运行

sudo tailscale up --advertise-routes=192.168.2.0/24

另外,为了让该设备能够自动发现其他网关的 Subnet,还需要启用 --accept-routes

所以,最终我们需要运行

sudo tailscale up --accept-routes --advertise-routes=192.168.2.0/24

`
最后,我们去再去控制台,点击这台设备,可以看到一个 Subnets - Awaiting Approval

image

点击 Edit ,勾选要公开的子网路由后,保存即可:

image

2.6 验证 Subnet 连接

目前已经配置完成,我们可以退出 SSH 连接,然后尝试 PING 办公点B 的路由器 192.168.2.1 来验证子网连接:

ping 192.168.2.1 -t

正在 Ping 192.168.2.1 具有 32 字节的数据:
来自 192.168.2.1 的回复: 字节=32 时间=140ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=7ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=6ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=6ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=7ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=7ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=6ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=8ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=8ms TTL=63
来自 192.168.2.1 的回复: 字节=32 时间=7ms TTL=63

2.7 根据需要,配置防火墙和 Tailscale ACL

  1. 设置访问策略(示例ACL):
{
  "acls": [
    {
      "action": "accept",
      "src": ["group:engineering"],
      "dst": ["subnet:192.168.1.0/24:*"]
    }
  ]
}
  1. 安全加固
# 配置UFW防火墙
sudo ufw allow 41641/udp # Tailscale端口
sudo ufw allow from 192.168.2.0/24

至此,接入 tailscale 的设备已经可以访问办公点B局域网中的任意设备了。只需对其他办公点如法炮制即可。


3. 其他问题

1. 局域网网段需要提前规划

要提前规划好各个办公点的网段,避免造成子网路由冲突。比如,办公点A 局域网使用 192.168.1.0/24 ,那么其他办公点就不可再使用此网段。

2. 性能问题

正常情况下,同一运营商使用 Tailscale 连接,延迟应该在 30ms 以内。除非设备是通过无线网络连接到办公点的路由器。

在我的实践中,各办公点 [厦门电信] 相互 Ping 路由器,延迟均在 10ms 以内,而 [厦门电信][南京电信] 的设备 Ping 延迟在 22ms 左右。

如果超过 100ms 的延迟,可能是因为多层 NAT 导致无法打通隧道,可以考虑尝试将路由器的 IPV6 功能开启,并为子网设备分发 IPV6 地址,以及打开 UPNP 功能,看看是否能有改善。因为目前 IPV6 一般下发的都是公网地址,不涉及 NAT 。

或者也可以考虑光猫桥接,但是要注意,需要自行在网络出口处安装防火墙设备配置防火墙规则,否则存在极大的安全漏洞。


感谢阅读。下一篇文章,我将会继续介绍,基于 Tailscale 组网后,我如何对设备进行状态监测。